const express = require("express");
const router = express.Router();
const path = require("path");
const pool = require("../pool.js");
const utils = require("../utils/index.js");
const utilsServer = require("../utils/serverInfo.js");
const moment = require("moment-timezone");
const multer = require("multer");
const AdmZip = require("adm-zip");
const AppInfoParser = require("app-info-parser");
const plist = require("plist");
const fs = require("fs");
const { readManifest } = require("node-aab-parser");
const msgUtils = require("../utils/feishu.js");
const crypto = require("crypto");
const CryptoJS = require("crypto-js");
const FormData = require("form-data");
const { exec } = require("child_process");
const config = require("../config");
const axios = require("axios");
const jwt = require("jsonwebtoken");
const jwksClient = require('jwks-rsa');
// const puppeteer = require('puppeteer');






router.post("/getAppMonitorList", async (req, res) => {
    let user = await utils.getUserRole(req, res);
    let { page, size } = utils.pageSize(req.body.page, req.body.size);
    let { package_name, dateRange, chat_id } = req.body;
    let sqlConditions = ["state = 0"];
    const sqlParams = [];
    if (chat_id) {
        sqlConditions.push("chat_id = ?");
        sqlParams.push(chat_id);
    }


    if (dateRange && dateRange.start && dateRange.end) {
        sqlConditions.push("update_date BETWEEN ? AND ?");
        sqlParams.push(dateRange.start, dateRange.end);
    }

    let sqlBase = `SELECT * FROM app_store_competitor`;
    let totalBase = "FROM app_store_competitor";
    if (sqlConditions.length > 0) {
        sqlBase += ` WHERE ${sqlConditions.join(" AND ")}`;
        totalBase += ` WHERE ${sqlConditions.join(" AND ")}`;
    }
    let sqlCount = `SELECT COUNT(*) AS total_count ${totalBase}`;

    let { total } = await utils.getListSum(sqlCount, sqlParams, res, req);

    sqlBase += " ORDER BY update_date DESC LIMIT ? OFFSET ?";
    sqlParams.push(size, page);
    await pool.query(sqlBase, sqlParams, (err, result) => {
        if (err) return res.send(utils.returnData({ code: -1, err, req }));
        result.forEach((element) => {
            element.create_date = moment(element.create_date)
                .tz("Asia/Shanghai")
                .format("YYYY-MM-DD HH:mm:ss");
            element.update_date = moment(element.update_date)
                .tz("Asia/Shanghai")
                .format("YYYY-MM-DD HH:mm:ss");
        });
        res.send(
            utils.returnData({
                data: result,
                total: total,
            })
        );
    });
});

//历史记录列表
router.post('/getHistoryList', async (req, res) => {
    let { state, id, dateRange } = req.body;

    let { page, size } = utils.pageSize(req.body.page, req.body.size);
    let sqlConditions = ["state = 0"];
    let sqlParams = [];
    if (dateRange && dateRange.start && dateRange.end) {
        sqlConditions.push("update_date BETWEEN ? AND ?");
        sqlParams.push(dateRange.start, dateRange.end);
    }

    if (id) {
        sqlConditions.push("link_id = ?");
        sqlParams.push(id);
    }
    let sqlBase = `SELECT * FROM app_store_competitor_tracking`;
    let totalBase = "FROM app_store_competitor_tracking";
    if (sqlConditions.length > 0) {
        sqlBase += ` WHERE ${sqlConditions.join(" AND ")}`;
        totalBase += ` WHERE ${sqlConditions.join(" AND ")}`;
    }
    let sqlCount = `SELECT COUNT(*) AS total_count ${totalBase}`;
    let { total } = await utils.getListSum(sqlCount, sqlParams, res, req);

    sqlBase += " ORDER BY update_date DESC LIMIT ? OFFSET ?";
    sqlParams.push(size, page);
    await pool.query(sqlBase, sqlParams, (err, result) => {
        if (err) return res.send(utils.returnData({ code: -1, err, req }));
        result.forEach((element) => {
            element.create_date = moment(element.create_date)
                .tz("Asia/Shanghai")
                .format("YYYY-MM-DD HH:mm:ss");
            element.update_date = moment(element.update_date)
                .tz("Asia/Shanghai")
                .format("YYYY-MM-DD HH:mm:ss");
        });
        res.send(
            utils.returnData({
                data: result,
                total: total,
            })
        );
    });
})

//保存
router.post('/save', async (req, res) => {
    try {
        const { name } = await utils.getUserInfo(req, res);

        const {
            id,
            chat_id,
            type,
            app_name,
            link,
            region,
            state

        } = req.body;


        let result;
        const updateBy = name;
        const currentTime = utils.formatDate(new Date());

        if (id) {
            // 更新操作
            const updateFields = [];
            const params = [];

            // 动态构建更新字段
            const fieldMap = {
                chat_id,
                type,
                app_name,
                link,
                region,
                state,
                update_by: updateBy,
                create_date: currentTime,
                update_date: currentTime
            };

            Object.entries(fieldMap).forEach(([key, value]) => {
                if (value !== undefined && key !== 'id') {
                    updateFields.push(`${key} = ?`);
                    params.push(value);
                }
            });

            params.push(id);
            const updateSql = `
                UPDATE app_store_competitor
                SET ${updateFields.join(', ')}
                WHERE id = ?
            `;

            result = await mysqlQuery(updateSql, params);
        } else {
            // 在插入新数据之前，查询是否有相同的链接
            const checkLinkSql = `
                SELECT id FROM app_store_competitor WHERE link = ? and state = 0
            `;
            const existingEntry = await mysqlQuery(checkLinkSql, [link]);

            if (existingEntry.length > 0) {
                // 如果已经存在相同的link
                return res.send({
                    code: 1,
                    message: '已存在相同的链接，无法新增',
                });
            }
            // 新增操作
            const newId = utils.createId();
            const insertSql = `
                INSERT INTO app_store_competitor (
                    id, chat_id, type, app_name,
                    link, region,state,
                      update_by, create_date, update_date
                ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            `;

            const insertParams = [
                newId,
                chat_id,
                type,
                app_name,
                link,
                region,
                state || 0,
                updateBy,     // 更新人
                currentTime,
                currentTime
            ];

            results = await mysqlQuery(insertSql, insertParams);
            results.insertId = newId;
        }

        res.send({
            code: 0,
            message: '操作成功',
            data: {
                id: id || results.insertId
            }
        });

        if (state && state != 0) return
        // 调用封装好的 Puppeteer 数据抓取函数
        try {
            let scrapeResult = null
            if (type == 'android') {
                scrapeResult = await scrapeData(link);
            } else {
                scrapeResult = await scrapeDataIOS(link);

            }
            if (scrapeResult) {
                // 将抓取结果存储到 app_store_competitor_tracking 表中
                const trackingId = utils.createId();
                const trackingInsertSql = `
                    INSERT INTO app_store_competitor_tracking (
                        id, link_id, type, app_name,
                        icon, version, shortDescription,
                        longDescription, version_update_date, create_date, update_date
                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                `;

                const trackingInsertParams = [
                    trackingId,
                    id || results.insertId,
                    type,
                    scrapeResult.title,
                    scrapeResult.icon,
                    scrapeResult.version,
                    scrapeResult.shortDescription,
                    scrapeResult.longDescription,
                    scrapeResult.version_update_data,
                    utils.formatDate(new Date()),
                    utils.formatDate(new Date())
                ];

                await mysqlQuery(trackingInsertSql, trackingInsertParams);
                let token = await msgUtils.getTenantAccessToken();
                let msg_type = "interactive";
                // let chatid = `oc_300d536417e7a4d6a47c27bc43b00bb0`;
                let chatid = chat_id;
                let img = await uploadImage(scrapeResult.icon, token);
                let at = `<at id="g1eff8g3">(产品)</at><at id="8d333cd2"></at><at id="5bfbfa32">(测试)</at><at id="c47a29d7">(测试)</at>`
                let contentMsg = {
                    schema: "2.0",
                    config: {
                        update_multi: true,
                        style: {
                            text_size: {
                                normal_v2: {
                                    default: "normal",
                                    pc: "normal",
                                    mobile: "heading"
                                }
                            }
                        }
                    },
                    body: {
                        direction: "vertical",
                        padding: "12px 12px 12px 12px",
                        elements: [
                            {
                                tag: "column_set",
                                columns: [
                                    {
                                        tag: "column",
                                        width: "weighted",
                                        elements: [
                                            {
                                                tag: "div",
                                                text: {
                                                    tag: "plain_text",
                                                    content: "",
                                                    text_size: "normal_v2",
                                                    text_align: "left",
                                                    text_color: "default"
                                                },
                                                margin: "0px 0px 0px 0px"
                                            },
                                            {
                                                tag: "markdown",
                                                content: `[竞品链接](${link})\n\n竞品名称:${scrapeResult.title}\n\n当前版本:${scrapeResult.version}\n\n[打开运营后台](https://insdoss.freeapptools.com/#/appMonitor)`,
                                                text_align: "left",
                                                text_size: "normal_v2",
                                                margin: "0px 0px 0px 0px"
                                            }
                                        ],
                                        vertical_align: "top",
                                        weight: 1
                                    },
                                    {
                                        tag: "column",
                                        width: "auto",
                                        elements: [
                                            {
                                                tag: "img",
                                                img_key: img,
                                                preview: true,
                                                scale_type: "crop_center",
                                                size: "medium"
                                            }
                                        ],
                                        vertical_align: "top"
                                    }
                                ]
                            }
                        ]
                    },
                    header: {
                        title: {
                            tag: "plain_text",
                            content: `竞品监控添加成功`
                        },
                        template: "yellow",
                        padding: "12px 12px 12px 12px"
                    }
                };
                let jsonString = JSON.stringify(contentMsg);
                await msgUtils.sendMessage(chatid, msg_type, jsonString, token);
            }
        } catch (error) {
            console.error('抓取页面数据失败:', error);
            // 你也可以选择在这里返回失败响应，或仅仅记录错误后继续执行其它逻辑
        }




    } catch (error) {
        console.error('保存失败:', error);
        res.status(500).json({
            code: 500,
            message: '服务器错误',
            error: error.message
        });
    }
});

// 封装 Puppeteer 操作的函数
async function scrapeData(link) {
    // 启动浏览器（默认为无头模式）
    const browser = await puppeteer.launch({
        args: ['--no-sandbox', '--disable-setuid-sandbox'],
    });
    const page = await browser.newPage();

    try {
        // 导航到目标网页
        await page.goto(link, {
            waitUntil: 'networkidle0',
            timeout: 30000 // 增加超时时间
        });

        // 等待目标元素加载完成
        await page.waitForSelector('.VfPpkd-Bz112c-LgbsSe.yHy1rc.eT1oJ.QDwDD.mN1ivc.VxpoF', { timeout: 10000 });
        // 在浏览器环境中执行 JavaScript 代码，获取相关数据
        const result = await page.evaluate(async () => {
            // 获取所有匹配的选择器元素
            const elements = document.querySelectorAll('.VfPpkd-Bz112c-LgbsSe.yHy1rc.eT1oJ.QDwDD.mN1ivc.VxpoF');

            if (elements.length > 0) {
                // 点击第一个匹配的元素
                elements[0].click();

                // 等待元素点击后的变化
                await new Promise(resolve => setTimeout(resolve, 2000));

                // 弹出框中获取数据
                const asElements = document.querySelectorAll('.VfPpkd-wzTsW');
                if (asElements.length === 0) {
                    return null;
                }
                const h5s = asElements[0].getElementsByTagName('h5');
                const title = h5s[0].textContent;
                const icons = asElements[0].getElementsByTagName('img');
                const icon = icons[0].src;

                // 查找短描述
                let shortDescription = '';
                const sfzrhdElements = document.getElementsByClassName('SfzRHd');
                for (let i = 0; i < sfzrhdElements.length; i++) {
                    const metaTags = sfzrhdElements[i].getElementsByTagName('meta');
                    for (let j = 0; j < metaTags.length; j++) {
                        if (metaTags[j].getAttribute('itemprop') === 'description') {
                            shortDescription = metaTags[j].getAttribute('content');
                            break;
                        }
                    }
                    if (shortDescription) break;
                }

                // 查找长描述
                let longDescription = '';
                const longDescriptionElement = document.querySelector('div[jsname="bN97Pc"]');
                if (longDescriptionElement && longDescriptionElement.firstElementChild) {
                    longDescription = longDescriptionElement.firstElementChild.textContent;
                }

                // 获取版本信息以及其他数据
                const vElements = asElements[0].querySelectorAll('.reAt0');
                const content = {
                    title: title,
                    icon: icon,
                    version: vElements[0] ? vElements[0].textContent : '',
                    shortDescription: shortDescription,
                    longDescription: longDescription,
                    version_update_data: vElements[8] ? vElements[8].textContent : ''
                };

                return content;
            }
            return null;
        });

        console.log('result:', result); // 打印最终结果
        return result;
    } catch (error) {
        console.error('执行过程中出错:', error);
        throw error;
    } finally {
        console.log('关闭浏览器');
        await browser.close();
    }
}
async function scrapeDataIOS(link) {
    // 启动浏览器（默认为无头模式）
    const browser = await puppeteer.launch({
        args: ['--no-sandbox', '--disable-setuid-sandbox'],
    });
    const page = await browser.newPage();
    page.on('console', msg => {
        const msgArgs = msg.args();
        const messages = msgArgs.map(arg => arg.toString()).join(' ');
        console.log(`[Browser Console] ${messages}`);
    });
    try {
        // 导航到目标网页
        await page.goto(link, {
            waitUntil: 'networkidle0',
            timeout: 30000 // 增加超时时间
        });

        // 等待目标元素加载完成
        await page.waitForSelector('.product-header__list__item', { timeout: 10000 });
        // 在浏览器环境中执行 JavaScript 代码，获取相关数据
        const result = await page.evaluate(async () => {
            //appname
            const h1Element = document.getElementsByTagName('h1')[0];
            const childNodes = h1Element.childNodes;
            let titleText = '';
            console.log(childNodes, '11111111111111')
            childNodes.forEach(node => {
                if (node.nodeType === Node.TEXT_NODE) {
                    titleText += node.textContent.trim();
                }
            });
            console.log(titleText, 'titleText')
            //icon
            const picture = document.getElementsByTagName('picture')[0];
            const source = picture.getElementsByTagName('source')[0];
            const srcset = source.getAttribute('srcset');
            const srcsetEntries = srcset.split(',');
            const firstEntry = srcsetEntries[0].trim();
            console.log(firstEntry.split(' ')[0], 'firstEntry.split')

            //短描述
            const h2Element = document.querySelector('h2.product-header__subtitle.app-header__subtitle');
            //长描述
            let weClampDivText = null
            const sections = document.getElementsByTagName('section');
            for (const section of sections) {
                const weClampDiv = section.querySelector('div.we-clamp');
                if (weClampDiv) {
                    weClampDivText = weClampDiv.textContent;
                }
            }

            // 获取应用版本号和发布时间
            const section = document.querySelector('section.whats-new');
            const timeElement = section.querySelector('time');
            const date = timeElement.getAttribute('aria-label'); // 或者直接 timeElement.textContent
            const versionElement = section.querySelector('.whats-new__latest__version');
            const version = versionElement.textContent;
            console.log(date, 'date')
            console.log(version, 'version')
            const content = {
                title: titleText,
                icon: firstEntry.split(' ')[0],
                version: version,
                shortDescription: h2Element ? h2Element.textContent : '',
                longDescription: weClampDivText,
                version_update_data: date
            };


            return content;
        });

        console.log('result:', result); // 打印最终结果
        return result;
    } catch (error) {
        console.error('执行过程中出错:', error);
        throw error;
    } finally {
        console.log('关闭浏览器');
        await browser.close();
    }
}
async function uploadImage(url, token) {
    // 将图片 URL 转换为二进制流
    const binaryImage = await urlToBinary(url);
    const response = await axios({
        method: 'post',
        url: 'https://open.feishu.cn/open-apis/im/v1/images',
        headers: {
            'Authorization': `Bearer ${token}`,
            'Content-Type': 'multipart/form-data'
        },
        data: {
            image_type: 'message',
            image: binaryImage
        }
    });
    return response.data.data.image_key;
}
async function urlToBinary(url) {
    const response = await axios.get(url, { responseType: 'arraybuffer' });
    return response.data;
}
// 增强版版本标准化函数
function normalizeVersion(version) {
    if (typeof version !== 'string') throw new Error('版本号必须为字符串');

    // 移除可能存在的v前缀
    const cleanVer = version.replace(/^v/i, '');

    // 拆分并验证数字格式，只取最多3个部分
    const parts = cleanVer.split('.').slice(0, 3);
    if (parts.some(p => !/^\d+$/.test(p))) {
        throw new Error(`非法版本号格式: ${version}`);
    }

    // 补零到3位并格式化为可比较字符串（每段补零到6位防止溢出）
    while (parts.length < 3) parts.push('0');
    return parts.map(p => p.padStart(6, '0')).join('.');
}

// 版本比较函数（可直接比较标准化后的字符串）
function compareVersions(a, b) {
    const aParts = a.split('.').map(Number);
    const bParts = b.split('.').map(Number);

    for (let i = 0; i < 3; i++) {
        if (aParts[i] !== bParts[i]) {
            return aParts[i] - bParts[i];
        }
    }
    return 0;
}
router.post('/check-version', async (req, res) => {
    const { package_name, version, language } = req.body;
    const now = Date.now();

    if (!package_name || !version || !language) {
        return res.status(400).json({
            code: 400,
            message: '缺少必要参数：package_name, version, language'
        });
    }


    try {
        //调试
        // let test = `SELECT *
        //     FROM app_version_management
        //     WHERE 
        //         package_name = ?
        //         AND state = 0
        //         AND status = 1`

        // let ress = await mysqlQuery(test, [package_name]);

        // console.log('目标时间戳（UTC）:', ress[0].effective_timestamp);
        // // 时间差（毫秒）
        // const timeDifference = ress[0].effective_timestamp - now;

        // // 输出时间差
        // console.log('距目标时间还有（毫秒）:', timeDifference);

        // // 格式化时间差
        // function formatTimeDifference(ms) {
        //     if (ms < 0) {
        //         return "目标时间已经过去，请检查配置";
        //     }

        //     const days = Math.floor(ms / (1000 * 60 * 60 * 24));
        //     const hours = Math.floor((ms % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
        //     const minutes = Math.floor((ms % (1000 * 60 * 60)) / (1000 * 60));
        //     const seconds = Math.floor((ms % (1000 * 60)) / 1000);

        //     return `距目标时间还有：${days} 天 ${hours} 小时 ${minutes} 分 ${seconds} 秒`;
        // }
        // // 输出格式化后的时间差
        // console.log(formatTimeDifference(timeDifference));

        // 第一步：基础查询
        const sql = `
            SELECT *
            FROM app_version_management
            WHERE 
                package_name = ?
                AND state = 0
                AND status = 1
                AND CAST(effective_timestamp AS UNSIGNED) < ?
            ORDER BY 
                CAST(SUBSTRING_INDEX(c_version, '.', 1) AS UNSIGNED) DESC,
                CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(c_version, '.', 2), '.', -1) AS UNSIGNED) DESC,
                CAST(SUBSTRING_INDEX(c_version, '.', -1) AS UNSIGNED) DESC
        `;

        const allResults = await mysqlQuery(sql, [package_name, now]);

        // 第二步：JS端版本校验
        const validResults = allResults.filter(item => {
            try {
                const userVer = normalizeVersion(version);
                const minVer = normalizeVersion(item.min_version);
                const maxVer = normalizeVersion(item.max_version);
                return userVer >= minVer && userVer <= maxVer;
            } catch (e) {
                console.error('版本号格式错误:', e);
                return false;
            }
        });

        // 第三步：处理返回结果
        if (validResults.length > 0) {
            const item = validResults[0];
            try {
                const details = JSON.parse(item.update_details);
                let content = null;

                // 查找用户指定的language
                for (const entry of details) {
                    if (entry && entry[language]) {
                        content = entry[language];
                        break;
                    }
                }

                // 未找到则查找en_US
                if (!content) {
                    for (const entry of details) {
                        if (entry && entry.en_US) {
                            content = entry.en_US;
                            break;
                        }
                    }
                }

                // 仍找不到则返回code=1
                if (!content) {
                    return res.json({
                        code: 1,
                        message: '未找到匹配的语言内容'
                    });
                }

                // 构建响应数据，移除update_details，添加content
                const { id, package_name, update_url, update_type, c_version } = item;
                const data = { id, c_version, package_name, update_url, update_type, content };

                res.json({
                    code: 0,
                    data: data,
                    message: 'success'
                });

            } catch (e) {
                // JSON解析失败或格式错误
                return res.json({
                    code: 1,
                    message: '版本详情解析失败'
                });
            }
        } else {
            // 无符合条件的版本，返回code=1
            res.json({
                code: 1,
                message: '未找到符合条件的版本信息'
            });
        }
    } catch (error) {
        console.error('数据库查询失败:', error);
        res.status(500).json({
            code: 500,
            message: '服务器内部错误',
            error: error.message
        });
    }
});

router.post('/test', (req, res) => {
    
})
async function mysqlQuery(sql, arr) {

    return new Promise((resolve, reject) => {
        pool.query(sql, arr, (error, results, fields) => {
            if (error) {
                return reject(error);
            }
            resolve(results);
        });
    });
}
module.exports = router;
